package com.cb.common.util;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;

import com.cb.common.menu.Menu;
import com.cb.common.webapp.context.RequestContext;
import com.cb.core.Constants;
import com.cb.core.util.AppUtil;
import com.cb.core.util.RequestUtil;
import com.cb.core.util.XmlUtil;
import com.cb.domain.model.system.AppRole;
import com.cb.domain.service.system.AppRoleManager;

/**
 * 
 * @author sdm
 * 后台菜单管理构建工具
 */
public class MenuUtil {
	private static final Log logger=LogFactory.getLog(MenuUtil.class);
	
	/**
	 * construct menus from configuration file 'menu-config.xml'
	 * @param treeFilePath
	 * @return
	 */
	public static Map<String,Menu> constructMenus(String treeFilePath){
		logger.info("============begin construct menu=============");
		Map<String,Menu> menuMap=new LinkedHashMap<String,Menu>();
		//String treeFilePath="D:/Dev/base/web/WEB-INF/classes/conf/menu-config.xml";
		Document doc=XmlUtil.load(treeFilePath);
		if(doc!=null){
			Element el=doc.getRootElement();
			
			List menus=el.selectNodes("./Menus/Menu");
			
			for(int i=0;i<menus.size();i++){
				Element e=(Element)menus.get(i);
				Menu menu = doConstructMenu(e);
				menuMap.put(menu.getName(), menu);
			}
		}

		logger.info("============end construct menu=============");
		return menuMap;
	}

	/**
	 * construct menu items from configuration file 'menu-config.xml'
	 * @param curElement
	 * @return
	 */
	public static List<Menu> constructMenuItems(Element curElement){
		List items=curElement.selectNodes("./Item");
		if(items.size()==0){
			return null;
		}
		List<Menu> itemList=new ArrayList<Menu>();
		for(int i=0;i<items.size();i++){
			Element el=(Element)items.get(i);
			Menu menuItem = doConstructMenu(el);
			itemList.add(menuItem);
		}
		return itemList;
	}
	
	/**
	 * reset menu role after change right of user role
	 * @param request
	 */
	public static void resetMenuRole(HttpServletRequest request){
		Map<String, Menu> menuMap=(Map<String, Menu>)request.getSession().getServletContext().getAttribute(Constants.APP_MENU);
		
		for (Menu menu : menuMap.values()) {
			setMenuRole(menu);
			resetMenuItemRole(menu.getItems());
		}
	}
	
	private static void resetMenuItemRole(List<Menu> items) {
		if (items == null)
			return;
		for (Menu menuItem : items) {
			setMenuRole(menuItem);
			resetMenuItemRole(menuItem.getItems());
		}
	}

	private static Menu doConstructMenu(Element e) {
		Attribute attName=e.attribute("name");
		Attribute attTitle=e.attribute("title");
		Attribute attRoles=e.attribute("roles");
		Attribute attPage=e.attribute("page");
		Attribute attDescription=e.attribute("description");
		Attribute attPattern=e.attribute("pattern");
		
		if(attName==null){
			throw new RuntimeException("MenuConfig XML <"+e.getName()+"> tag's name attribute must be filled.");
		}
		if(attTitle==null){
			throw new RuntimeException("MenuConfig XML <"+e.getName()+"> tag's title attribute must be filled.");
		}
		
		Menu menu=new Menu();
		menu.setName(attName.getValue());
		menu.setTitle(attTitle.getValue());

		if(attPage!=null){
			menu.setPage(attPage.getValue());
		}
		if(attRoles!=null){
			menu.setRoles(attRoles.getValue());
		}
		if(attDescription!=null){
			menu.setDescription(attDescription.getValue());
		}
		if(attPattern!=null){
			menu.setPattern(attPattern.getValue());
		}else{
			menu.setPattern("/"+menu.getPage()+"*");
		}
		// set menu role
		setMenuRole(menu);
		menu.setItems(constructMenuItems(e));
		return menu;
	}
	
	private static void setMenuRole(Menu menu) {
		AppRoleManager roleManager = (AppRoleManager)AppUtil.getById("appRoleManagerImpl");
		List<AppRole> roles = roleManager.getAll(new String[]{"resources"});
		for (AppRole role : roles) {
			String roleName = role.getRoleName();
			if (role.isPermitAll()) {
				menu.addPermitRole(roleName);
				continue;
			}
			if (role.hasResource(menu.getName())) {
				menu.addPermitRole(roleName);
				continue;
			}
			if (role.hasNoResource(menu.getName())) {
				menu.removePermitRole(roleName);
				continue;
			}
		}
	}
	
	/**
	 * draw menus for display
	 * 
	 * template:
	 * <li id='homeMenu'><a href='/crm/admin/main.do'>首 页</a></li>
	 */
	public static String drawMenus(HttpServletRequest request){
		StringBuffer drawMenu=new StringBuffer();
		String contextPath=request.getContextPath();
		String currentModule=MenuUtil.getModulesNameFromRequest(request);
		Map<String, Menu> menuMap=(Map<String, Menu>)request.getSession().getServletContext().getAttribute(Constants.APP_MENU);

		for (Menu menu : menuMap.values()) {
			if (menu.isVisible(RequestContext.getCurrentSystemUser())) {
				drawMenu.append("<li id='")
					.append(menu.getName())
					.append("'");
				if (StringUtils.equals(menu.getName(), currentModule)) {
					drawMenu.append(" class='active'");
				}
				drawMenu.append("><a href='")
					.append(contextPath+"/"+menu.getPage())
					.append("'>")
					.append(menu.getTitle())
					.append("</a></li>\r");
			}
		}
		return drawMenu.toString();
	}

	/**
	 * draw sub-menus for display
	 * 
	 * template:
	 * <div class='boxed'>
	 * 		<h2 class='title'><a href='/crm/admin/system/appUsers.do'>安全管理</a></h2>
	 * 		<div class='content'>
	 * 			...... (from drawSubMenuItems())
	 * 		</div>
	 * </div>
	 * 
	 */
	public static String drawSubMenus(HttpServletRequest request,String modules){
		StringBuffer drawMenu=new StringBuffer();
		String contextPath=request.getContextPath();

		Map<String, Menu> menuMap=(Map<String, Menu>)request.getSession().getServletContext().getAttribute(Constants.APP_MENU);
		Menu menu=menuMap.get(modules);
		if(menu==null)return drawMenu.toString();
		if (menu.isVisible(RequestContext.getCurrentSystemUser())) {
//		Set<AppRole> appRoles=RequestContext.getCurrentUser().getRoles();
			List menuItems=menu.getItems();
			if(menuItems!=null){
				for(int i=0;i<menuItems.size();i++){
					Menu menuItem=(Menu)menuItems.get(i);
					Integer index=i+1;
					if (menuItem.isVisible(RequestContext.getCurrentSystemUser())) {
						drawMenu.append("<li>");
						drawMenu.append("<a href='#Menu=ChildMenu"+index+"' onclick=\"javascript:DoMenu('ChildMenu"+index+"')\">");
						drawMenu.append("<strong style='color:#F00;'>&gt;</strong>");
						if (StringUtils.isNotBlank(menuItem.getPage()))
							drawMenu.append("<a href='").append(contextPath+"/"+menuItem.getPage()).append("'>").append(menuItem.getTitle()).append("</a>");
						else{
							drawMenu.append(menuItem.getTitle());
						}
							drawMenu.append("</a>");
							
						if(menuItem.getItems()!=null){
							
							HttpServletRequest httpRequest = (HttpServletRequest) request;
							String url = httpRequest.getRequestURI();
							String classValue="collapsed";
						/*	if(url==menuItem.getPage()){
								classValue="expanded";
							}*/
							drawMenu.append("<ul id='ChildMenu"+index+"' class='"+classValue+"'>");
							
							drawSubMenuItems(menuItem,drawMenu,contextPath);
							drawMenu.append("</ul>");
						}
						drawMenu.append("</li>");
						
					/*	  <li class="newslistblue"><a href="javascript:void(0)" onclick="tabs('1');" ><strong style="color:#F00;">&gt;&gt;</strong>国内订单情况</a></li>
						  <span id="_1" onclick="cl('1');"><img src="../image/del.gif"/></span>
						  <li id="tab_a1" style="display:none">
							   <p><a href="../fares/gl_order.htm">&ndash;&nbsp;国内订单管理</a></p>
						   </li>*/
					}
				}
			}
		}
		return drawMenu.toString();
	}
	
	/**
	 * draw sub-menus itme for display
	 * 
	 * template:
	 * <ul>
	 * 		<li class='first'><a href='/crm/admin/system/appUsers.do'>用户管理</a></li>
	 * 		<li><a href='/crm/admin/system/editAppUser.do'>添加用户</a></li>
	 * </ul>
	 */
	public static void drawSubMenuItems(Menu menuItem,StringBuffer drawMenu,String contextPath){
		List items=menuItem.getItems();
		if(items==null) return;
//		drawMenu.append("<ul>\r");
		for(int i=0;i<items.size();i++){
			Menu im=(Menu)items.get(i);
			if (im.isVisible(RequestContext.getCurrentSystemUser())) {
				/*if(i==0){
					drawMenu.append("<li class='first'>");
				}else{
					drawMenu.append("<li>");
				}*/
				drawMenu.append("<li>");
				if (StringUtils.isNotBlank(im.getPage()))
					drawMenu.append("<a href='").append(contextPath+"/"+im.getPage()).append("'>&ndash;&nbsp;").append(im.getTitle()).append("</a>");
				else
					drawMenu.append(im.getTitle());
				drawMenu.append("</li>");
//				drawMenu.append("</li>\r");
			}
//			if(im.getItems()!=null){
//				sb.append("<li>\r");
//				drawSubMenuItems(im,sb,contextPath);
//				sb.append("</li>\r");
//			}
			
		}
//		drawMenu.append("</ul>\r");
	}
	
	public static String getModulesNameFromRequest(HttpServletRequest request){
		String modules="home";
		String path=request.getRequestURI();
		int index=path.indexOf("/admin/");
		if (index!=-1){
			path=path.substring(index+7);
			index=path.indexOf("/");
			if(index!=-1){
				modules=path.substring(0,index);
			}
		}
		modules+="Menu";
		return modules;
	}
	
}
